home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / gcc / gempp19.zoo / gem++19 / src / gemfw.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-19  |  9.9 KB  |  458 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is Copyright 1992,1993 by Warwick W. Allison.
  4. //  This file is part of the gem++ library.
  5. //  You are free to copy and modify these sources, provided you acknowledge
  6. //  the origin by retaining this notice, and adhere to the conditions
  7. //  described in the file COPYING.LIB.
  8. //
  9. /////////////////////////////////////////////////////////////////////////////
  10.  
  11. #include <aesbind.h>
  12. #include <osbind.h>
  13. #include "gemfw.h"
  14. #include "gemo.h"
  15. #include "geme.h"
  16. #include "scancode.h"
  17.  
  18. // The global int "StartObject" links the call to RedrawOverlaps
  19. // with RedrawOverlaps' calls to Redraw.  An alternative solution
  20. // would be to have RedrawOverlaps accept a parameter which it
  21. // just blindly passed to Redraw, however this would involve a
  22. // void* pointer, and would delocalize the issue.  When setting
  23. // the StartObject, be sure to reset it to ROOT, since redraw
  24. // events, etc. will also call RedrawOverlaps.
  25. static int StartObject=ROOT;
  26.  
  27. GEMformwindow::GEMformwindow(GEMactivity& act, const GEMrsc& in, int RSCindex) :
  28.     GEMwindow(act,CLOSER|MOVER|NAME), GEMform(in, RSCindex),
  29.     rubberwidth(FALSE),
  30.     rubberheight(FALSE)
  31. {
  32.     GRect workArea(Obj[ROOT].X(), Obj[ROOT].Y(),
  33.         Obj[ROOT].Width(), Obj[ROOT].Height());
  34.     Max = Pos = workArea;
  35.     initialized = TRUE;
  36.     Align(0,0,2,2); // For simple shade patterns (complex ones require 4x4)
  37.  
  38.     ButtonEventFlags(1);
  39. }
  40.  
  41. GEMformwindow::GEMformwindow(GEMactivity& act, const GEMrsc& in, int RSCindex, int Parts) :
  42.     GEMwindow(act,Parts), GEMform(in, RSCindex),
  43.     rubberwidth(bool(Parts&SIZER && !(Parts&HSLIDE))),
  44.     rubberheight(bool(Parts&SIZER && !(Parts&VSLIDE)))
  45. {
  46.     GRect workArea(Obj[ROOT].X(), Obj[ROOT].Y(),
  47.         Obj[ROOT].Width(), Obj[ROOT].Height());
  48.     Max = Pos = workArea;
  49.     initialized = TRUE;
  50.     Align(0,0,2,2); // For simple shade patterns (complex ones require 4x4)
  51.  
  52.     // Assumes ColumnWidth() and LineHeight() are 1.
  53.     SetTotalColumns(Obj[ROOT].Width());
  54.     SetTotalLines(Obj[ROOT].Height());
  55.     SetVisibleColumns(Obj[ROOT].Width());
  56.     SetVisibleLines(Obj[ROOT].Height());
  57.  
  58.     ButtonEventFlags(1);
  59. }
  60.  
  61. GEMformwindow::GEMformwindow(const GEMformwindow& copy) :
  62.     GEMwindow(copy), GEMform(copy),
  63.     rubberwidth(copy.rubberwidth),
  64.     rubberheight(copy.rubberheight)
  65. {
  66.     // GEMwindow is exactly the same, except position changes slightly.
  67.     Obj[ROOT].MoveTo(Pos.g_x,Pos.g_y);
  68. }
  69.  
  70. static
  71. bool GetKey(int& Key)
  72. // Modal.  Menu bar is not active while getting keys.
  73. // Returns FALSE if non-key event arrives.
  74. {
  75.     int Pipe[32];
  76.     int mx,my,button,meta,count;
  77.  
  78.     wind_update(BEG_MCTRL);
  79.  
  80.     int got=evnt_multi(MU_KEYBD|MU_BUTTON,
  81.                 1,1,1,0,0,0,0,0,0,0,0,0,0,
  82.                 Pipe,0,&mx,&my,&button,&meta,&Key,&count
  83.             );
  84.  
  85.     wind_update(END_MCTRL);
  86.  
  87.     if (got&MU_KEYBD) {
  88.         return TRUE;
  89.     }
  90.  
  91.     return FALSE;
  92. }
  93.  
  94. void GEMformwindow::Redraw(const GRect& area)
  95. {
  96.     if (IsOpen()) {
  97.         objc_draw(Obj, StartObject, MAX_DEPTH, area.g_x, area.g_y, area.g_w, area.g_h);
  98.     }
  99. }
  100.  
  101. bool GEMformwindow::ScrollByBlitting() const
  102. {
  103.     // Actually, without WINX, patterns may look poor with blit scrolling.
  104.     return TRUE;
  105. }
  106.  
  107. void GEMformwindow::SetWorkRect(const GRect& r)
  108. // Do the normal SetWorkRect, then adjust object tree position.
  109. {
  110.     GEMwindow::SetWorkRect(r);
  111.     GEMrawobject* root=&Obj[ROOT];
  112.     GEMobject* croot=root->Cook();
  113.  
  114.     if (croot) {
  115.         croot->MoveTo(Pos.g_x-LeftColumn()*ColumnWidth(),
  116.             Pos.g_y-TopLine()*LineHeight());
  117.         bool changed=FALSE;
  118.         if (rubberwidth && Pos.g_w!=croot->Width()) {
  119.             croot->SetWidth(Pos.g_w);
  120.             changed=TRUE;
  121.         }
  122.         if (rubberheight && Pos.g_h!=croot->Height()) {
  123.             croot->SetHeight(Pos.g_h);
  124.             changed=TRUE;
  125.         }
  126.         if (changed) {
  127.             RedrawObject(0);
  128.         }
  129.     } else {
  130.         root->MoveTo(Pos.g_x-LeftColumn()*ColumnWidth(),
  131.             Pos.g_y-TopLine()*LineHeight());
  132.     }
  133. }
  134.  
  135. void GEMformwindow::HFlushSlider()
  136. // Adjust object tree position.
  137. {
  138.     GEMwindow::HFlushSlider();
  139.     Obj[ROOT].MoveTo(Pos.g_x-LeftColumn()*ColumnWidth(),
  140.         Pos.g_y-TopLine()*LineHeight());
  141. }
  142.  
  143. void GEMformwindow::VFlushSlider()
  144. // Adjust object tree position.
  145. {
  146.     GEMwindow::VFlushSlider();
  147.     Obj[ROOT].MoveTo(Pos.g_x-LeftColumn()*ColumnWidth(),
  148.         Pos.g_y-TopLine()*LineHeight());
  149. }
  150.  
  151. static
  152. void WaitForNoButton()
  153. {
  154.     int X,Y,Buttons,Metas;
  155.  
  156.     do graf_mkstate(&X,&Y,&Buttons,&Metas); while (Buttons);
  157. }
  158.  
  159.  
  160. // Any point in making this a method of GEMobjects?
  161. static
  162. void WatchBox(GEMobject *O)
  163. {
  164.     int X,Y,Buttons,Metas;
  165.     bool OldOn=O->Selected();
  166.     bool On=FALSE;
  167.  
  168.     do {
  169.         graf_mkstate(&X,&Y,&Buttons,&Metas);
  170.         On=O->ContainsPoint(X,Y);
  171.         if (On!=OldOn) {
  172.             OldOn=On;
  173.             O->Selected(On);
  174.             O->Redraw();
  175.         }
  176.     } while (Buttons);
  177. }
  178.  
  179. static
  180. int FindEditable(GEMrawobject *Obj, int Object, int way)
  181. {
  182.     int c=Object+way;
  183.  
  184.     while (1) {
  185.         if (c<0) while (!(Obj[++c].LastObject()));
  186.         else if (Obj[c].Editable() || c==Object) return c;
  187.         else if (Obj[c].LastObject() && way>0) c=0;
  188.         else c+=way;
  189.     }
  190. }
  191.  
  192. void GEMformwindow::Edit(int Object, int Index)
  193. {
  194.     // The Atari Compendium says "Reserved for future use.  Do not call."
  195.     //objc_edit(Obj,Object,0,Index,EDSTART,&Index);
  196.  
  197.     objc_edit(Obj,Object,0,Index,EDINIT,&Index);
  198.  
  199.     WaitForNoButton();
  200.  
  201.     while (1) {
  202.         int Key;
  203.  
  204.         if (!GetKey(Key)) {
  205.             objc_edit(Obj,Object,0,Index,EDEND,&Index);
  206.             return;
  207.         }
  208.  
  209.         switch (Key>>8) {
  210.             case KEY_RETURN:
  211.                 objc_edit(Obj,Object,0,Index,EDEND,&Index);
  212.                 return;
  213.         break;    case KEY_UP:
  214.                 objc_edit(Obj,Object,0,Index,EDEND,&Index);
  215.                 Object=FindEditable(Obj,Object,-1);
  216.                 objc_edit(Obj,Object,0,Index,EDINIT,&Index);
  217.         break;    case KEY_DOWN:
  218.                 objc_edit(Obj,Object,0,Index,EDEND,&Index);
  219.                 Object=FindEditable(Obj,Object,+1);
  220.                 objc_edit(Obj,Object,0,Index,EDINIT,&Index);
  221.         break;    default:
  222.                 objc_edit(Obj,Object,Key,Index,EDCHAR,&Index);
  223.         }
  224.  
  225.     }
  226. }
  227.  
  228. static
  229. bool inside(int x, int y, const GRECT& pt)
  230. {
  231.     return ( x>=pt.g_x && y>=pt.g_y && x<pt.g_x+pt.g_w && y<pt.g_y+pt.g_h );
  232. }
  233.  
  234. void GEMformwindow::Top(const GEMevent& e)
  235. {
  236.     if (!inside(e.X(),e.Y(),WorkRect()) || Click(e)==IgnoredClick) GEMwindow::Top(e);
  237. }
  238.  
  239. GEMfeedback GEMformwindow::Click(const GEMevent& e)
  240. {
  241.     GEMfeedback result=IgnoredClick;
  242.  
  243.     int o=objc_find(Obj,ROOT,MAX_DEPTH,e.X(),e.Y());
  244.  
  245.     if (o>=0) {
  246.         while (o>=0 && !Obj[o].Disabled() && !Obj[o].RadioButton()
  247.           && !Obj[o].TouchExit() && !Obj[o].Editable()
  248.           && !Obj[o].Exit() && !Obj[o].Selectable()) {
  249.             o=Parent(o);
  250.         }
  251.         if (o<0) o=0;
  252.  
  253.         GEMobject *O=operator[](o).Cook();
  254.  
  255.         int dummy=O==0;
  256.  
  257.         if (dummy) O=new GEMobject(*this,o);
  258.  
  259.         if (!O->Disabled()) {
  260.             int X,Y;
  261.             objc_offset(Obj,o,&X,&Y);
  262.  
  263.             if (O->TouchExit())
  264.                 result=DoItem(o,e);
  265.  
  266.             if (O->RadioButton()) {
  267.                 if (!O->Selected()) {
  268.                     int p=Parent(o);
  269.                     int c=Obj[p].Head();
  270.                     while (c!=p) {
  271.                         GEMobject P(*this,c);
  272.                         if (P.Selected() && P.RadioButton()) {
  273.                             P.Deselect();
  274.                             P.Redraw();
  275.                         }
  276.                         c=Obj[c].Next();
  277.                     }
  278.                     O->Select();
  279.                     O->Redraw();
  280.  
  281.                     result=DoItem(o,e);
  282.  
  283.                     if (result==IgnoredClick) result=ContinueInteraction;
  284.                 } else 
  285.                     result=ContinueInteraction;
  286.             } else {
  287.                 if (O->Selectable() && !O->Exit()) {
  288.                     if (O->Selected()) O->Deselect();
  289.                     else O->Select();
  290.                     O->Redraw();
  291.  
  292.                     result=DoItem(o,e);
  293.                     if (result==IgnoredClick) result=ContinueInteraction;
  294.                     WaitForNoButton();
  295.                 }
  296.             }
  297.  
  298.             if (O->Editable()) {
  299.                 Edit(o,1/* Column */);
  300.                 result=DoItem(o,e);
  301.                 if (result==IgnoredClick) result=ContinueInteraction;
  302.             }
  303.  
  304.             if (O->Exit()) {
  305.                 result=ContinueInteraction;
  306.                 if (O->Selectable()) {
  307.                     WatchBox(O);
  308.                     if (O->Selected()) {
  309.                         result=DoItem(o,e);
  310.                         if (result==IgnoredClick) result=ContinueInteraction;
  311.                         O->Deselect();
  312.                         O->Redraw();
  313.                     }
  314.                 } else {
  315.                     WaitForNoButton();
  316.                 }
  317.             }
  318.         }
  319.         if (dummy) delete O;
  320.     }
  321.  
  322.     if (result==IgnoredClick && (ButtonEventFlags(-1)&1)) {
  323.         GEMwindow::Top(e);
  324.         result=ContinueInteraction;
  325.     }
  326.  
  327.     return result;
  328. }
  329.  
  330.  
  331. void GEMformwindow::RedrawObject(int RSCindex)
  332. {
  333.     if (IsOpen()) {
  334.         int x,y;
  335.         objc_offset(Obj,RSCindex,&x,&y);
  336.         GRect R(x,y,Obj[RSCindex].Width(),Obj[RSCindex].Height());
  337.         StartObject=RSCindex;
  338.         RedrawOverlaps(R);
  339.         StartObject=ROOT;
  340.     }
  341. }
  342.  
  343. void GEMformwindow::RedrawObject(int RSCindex,int Cx,int Cy,int Cw,int Ch) // Clipped
  344. {
  345.     if (IsOpen()) {
  346.         int x,y;
  347.         objc_offset(Obj,RSCindex,&x,&y);
  348.         GRect R(x+Cx,y+Cy,Cw,Ch);
  349.         StartObject=RSCindex;
  350.         RedrawOverlaps(R);
  351.         StartObject=ROOT;
  352.     }
  353. }
  354.  
  355. void GEMformwindow::AlignObject(int RSCindex, int xmlt=8, int ymlt=1)
  356. {
  357.     GEMform::AlignObject(RSCindex,xmlt,ymlt);
  358.  
  359.     int j;
  360.     int x,y;
  361.     wind_calc(1,parts,xoffset,yoffset,50,50,&x,&y,&j,&j);
  362.  
  363.     Align(x,y,xmult,ymult);
  364. }
  365.  
  366. bool GEMformwindow::IsOpen() const
  367. {
  368.     return GEMwindow::IsOpen();
  369. }
  370.  
  371. bool GEMformwindow::RubberWidth()
  372. {
  373.     return rubberwidth;
  374. }
  375.  
  376. bool GEMformwindow::RubberHeight()
  377. {
  378.     return rubberheight;
  379. }
  380.  
  381. void GEMformwindow::RubberWidth(bool yes)
  382. {
  383.     rubberwidth=yes;
  384. }
  385.  
  386. void GEMformwindow::RubberHeight(bool yes)
  387. {
  388.     rubberheight=yes;
  389. }
  390.  
  391. void GEMformwindow::Rubber(bool yes)
  392. {
  393.     RubberWidth(yes);
  394.     RubberHeight(yes);
  395. }
  396.  
  397. class GEMfwRect : public GRect {
  398. public:
  399.     GRect box;
  400.     GRect obox;
  401. };
  402.  
  403. GRect* GEMformwindow::FirstClip(int RSCobject)
  404. {
  405.     if (IsOpen()) {
  406.         GEMfwRect* result=new GEMfwRect;
  407.  
  408.         objc_offset(Obj,RSCobject,&result->obox.g_x,&result->obox.g_y);
  409.         result->obox.g_w=Obj[RSCobject].Width();
  410.         result->obox.g_h=Obj[RSCobject].Height();
  411.  
  412.         wind_get(Handle(), WF_FIRSTXYWH,
  413.             &result->box.g_x, &result->box.g_y, &result->box.g_w, &result->box.g_h);
  414.  
  415.         return NextClip(result);
  416.     } else {
  417.         return 0;
  418.     }
  419. }
  420.  
  421. GRect* GEMformwindow::NextClip(GRect* prev)
  422. {
  423.     GEMfwRect* rect=(GEMfwRect*)prev;
  424.  
  425.     while (rect->box.g_w && rect->box.g_h) {
  426.         if (rc_intersect(&rect->obox, &rect->box)) {
  427.             rect->g_x=rect->box.g_x;
  428.             rect->g_y=rect->box.g_y;
  429.             rect->g_w=rect->box.g_w;
  430.             rect->g_h=rect->box.g_h;
  431.             // Get ready for the next call to this.
  432.             wind_get(Handle(), WF_NEXTXYWH,
  433.                 &rect->box.g_x, &rect->box.g_y, &rect->box.g_w, &rect->box.g_h);
  434.  
  435.             return rect;
  436.         }
  437.         wind_get(Handle(), WF_NEXTXYWH,
  438.             &rect->box.g_x, &rect->box.g_y, &rect->box.g_w, &rect->box.g_h);
  439.     }
  440.  
  441.     delete rect;
  442.  
  443.     return 0;
  444. }
  445.  
  446. // To slow scrolling in pixels, and this improves pattern scrolling.
  447.  
  448. int GEMformwindow::VLineAmount()
  449. {
  450.     return 4;
  451. }
  452.  
  453. int GEMformwindow::HColumnAmount()
  454. {
  455.     return 4;
  456. }
  457.  
  458.